package com.wz.dhs.config;

import cn.hutool.core.lang.UUID;
import com.wz.dhs.constant.RedisKeyConstant;
import com.wz.dhs.exception.BusinessException;
import com.wz.dhs.model.LanguageContextHolder;
import com.wz.dhs.model.UserContextHolder;
import com.wz.dhs.model.UserTokenCache;
import com.wz.dhs.model.common.ResultCode;
import com.wz.dhs.utils.RedisUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.MDC;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;


import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

@Component
@Slf4j
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {

    @Autowired
    private UrlIgnoreConfig config;



    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, javax.servlet.FilterChain filterChain) throws ServletException, IOException {
        String uuid = UUID.randomUUID().toString().replace("-","");
        MDC.put("traceId",uuid);
        log.info("当前请求路径:{},流水号:{}",request.getRequestURI(),uuid);
        if (config.matchUrl(request.getRequestURI()) || request.getHeader("token").equals("123")) {
            //白名单请求包含静态文件，缓存到ng
            response.addHeader("X-Accel-Expires","3600");
            UsernamePasswordAuthenticationToken authenticationToken =
                    new UsernamePasswordAuthenticationToken(
                            null,
                            null,
                            null);
            SecurityContextHolder.getContext().setAuthentication(authenticationToken);
            filterChain.doFilter(request, response);
            return;
        }

        // 获取token
        String token = request.getHeader("token");
        if (StringUtils.isBlank(token)) {
            //直接放行 让后面原生的 security 去拦截
            filterChain.doFilter(request, response);
            return;
        }

        // 从redis 获取用户信息
        String redisKey = String.format(RedisKeyConstant.USER_TOKEN_PREFIX, token);
        UserTokenCache user = RedisUtils.getValue(redisKey, UserTokenCache.class);
        if (Objects.isNull(user)) {
            throw new BusinessException(ResultCode.AUTH_FAIL.getCode());
        }
        RedisUtils.setExpireTime(redisKey, TimeUnit.DAYS, 15L);
        String loginKey = String.format(RedisKeyConstant.USER_LOGIN_STATUS, user.getUserId());
        RedisUtils.setExpireTime(loginKey, TimeUnit.DAYS, 15L);
        // 将用户信息存入SecurityContextHolder
        UsernamePasswordAuthenticationToken authenticationToken =
                new UsernamePasswordAuthenticationToken(
                        user.getUserId(),
                        null,
                        null);
        SecurityContextHolder.getContext().setAuthentication(authenticationToken);
        try {
            UserContextHolder.setUserInfo(user);
            LanguageContextHolder.setLanguage(StringUtils.isNotBlank(request.getHeader("Accept-Language")) ? request.getHeader("Accept-Language") : "zh-CN");
            filterChain.doFilter(request, response);
        }
        catch (Exception e){
            log.error("[请求出现异常:{}]",e);
        }
        finally {
            UserContextHolder.remove();
            LanguageContextHolder.remove();
            MDC.clear();
        }
    }
}
